using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace _2Dshooter
{
    public class Object
    {

        
    }
    public class Enemy
    {
        public Texture2D image;
        public Vector2 position;
        public float rotation;
        public float speed;
        public int scale = 1;
        public Enemy(ContentManager content, string imagefile)
        {
            image = content.Load<Texture2D>(imagefile);
        }
        public void SetUp(Vector2 pos, float rot)
        {
            position = pos;
            rotation = rot;
        }
    }
    public class Cannon
    {
        public Texture2D image;
        public Vector2 position;
        public float rotation;
        public Vector2 center;
        public Cannon(ContentManager content, string imagefile)
        {
            image = content.Load<Texture2D>(imagefile);
        }
        public void SetUp(Vector2 pos, float rot)
        {
            position = pos;
            rotation = rot;
            center = new Vector2(image.Width / 2, image.Height / 2);
        }
    }
    public class CannonBall
    {
        public Texture2D image;
        public Vector2 position;
        public Vector2 velocity;
        public float rotation;
        public int scale = 1;
        public CannonBall(ContentManager content, string imagefile)
        {
            image = content.Load<Texture2D>(imagefile);
        }
        public void SetUp(Vector2 pos, float rot)
        {
            position = pos;
            rotation = rot;
        }
    }
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        Cannon cannon;
        List<Enemy> enemies;
        List<CannonBall> cannonballs;
        KeyboardState keystate = Keyboard.GetState();
        KeyboardState lastkeystate = Keyboard.GetState();
        MouseState mousestate = Mouse.GetState();
        MouseState lastmousestate = Mouse.GetState();
        Vector2 centerOfScreen;
        private const float MISSILESPEED = 5;
        private const float MAXENEMYSPEED = 4;
        Random r;
        int score = 0;
        private SpriteFont font;
        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            graphics.PreferredBackBufferWidth = 800;
            graphics.PreferredBackBufferHeight = 600;
            graphics.ApplyChanges();
            IsMouseVisible = true;
            centerOfScreen = new Vector2(graphics.PreferredBackBufferWidth / 2, graphics.PreferredBackBufferHeight / 2);
            r = new Random();
            Content.RootDirectory = "Content";
        }


        protected override void Initialize()
        {

            base.Initialize();
        }


        protected override void LoadContent()
        {
            font = Content.Load<SpriteFont>("font");
            spriteBatch = new SpriteBatch(GraphicsDevice);
            cannon = new Cannon(Content, "CannonFodder");
            enemies = new List<Enemy>();
            cannonballs = new List<CannonBall>();
            enemies = SetUpEnemies(enemies, 5);
            cannon.SetUp(new Vector2(50, 500), 0.0f);
        }
        private List<Enemy> SetUpEnemies(List<Enemy> EnEmies, int numberOfEnemies)
        {
            for (int i = 0; i < numberOfEnemies; i++)
            {
                Enemy newenemy = new Enemy(Content, "Enemy");
                newenemy.position = new Vector2(graphics.PreferredBackBufferWidth, r.Next(0,graphics.PreferredBackBufferHeight - 100));
                newenemy.speed = (float)r.NextDouble() * MAXENEMYSPEED;
                newenemy.speed = Math.Min(2, 4);
                EnEmies.Add(newenemy);
            }
            return EnEmies;
        }
        protected override void UnloadContent()
        {
        }

        protected override void Update(GameTime gameTime)
        {
            if (keystate.IsKeyDown(Keys.Escape))
                this.Exit();
            UpdatePlayer();
            UpdateEnemies();
            UpdateCannonballs();

            base.Update(gameTime);
        }

        private void UpdateCannonballs()
        {
            for (int i = 0; i < cannonballs.Count; i++ )
            {
                cannonballs[i].position += cannonballs[i].velocity;
                if (cannonballs[i].position.X < 0 || cannonballs[i].position.X > graphics.PreferredBackBufferWidth || cannonballs[i].position.Y < 0 || cannonballs[i].position.Y > graphics.PreferredBackBufferHeight)
                {
                    cannonballs.Remove(cannonballs[i]);
                    i--;
                }
            }
        }

        private void UpdatePlayer()
        {
            if (mousestate.LeftButton == ButtonState.Pressed && lastmousestate.LeftButton == ButtonState.Released)
                FireCannon();
            cannon.rotation = (float)Math.Atan2((double)mousestate.Y - (double)cannon.position.Y, (double)mousestate.X - (double)cannon.position.X) + MathHelper.PiOver2;
            Vector2 pos1 = new Vector2(mousestate.X, mousestate.Y);
            Vector2 pos2 = centerOfScreen;
            if (keystate.IsKeyDown(Keys.A))
                cannon.rotation -= 0.05f;
            if (keystate.IsKeyDown(Keys.D))
                cannon.rotation += 0.05f;
            lastkeystate = keystate;
            keystate = Keyboard.GetState();
            lastmousestate = mousestate;
            mousestate = Mouse.GetState();
        }

        private void FireCannon()
        {
            CannonBall newball = new CannonBall(Content, "missile");
            newball.SetUp(cannon.position, cannon.rotation);
            newball.velocity = new Vector2(mousestate.X - cannon.position.X, mousestate.Y - cannon.position.Y);
            newball.velocity.Normalize();
            newball.velocity *= MISSILESPEED;
            cannonballs.Add(newball);
        }

        private void UpdateEnemies()
        {
            foreach (Enemy enemy in enemies)
            {
                enemy.position.X -= enemy.speed;
                if (enemy.position.X < 0 || enemy.position.X > graphics.PreferredBackBufferWidth || enemy.position.Y < 0 || enemy.position.Y > graphics.PreferredBackBufferHeight)
                {
                    enemy.position.X =  graphics.PreferredBackBufferWidth - 1;
                }
                Rectangle enemyHitbox = new Rectangle((int)enemy.position.X, (int)enemy.position.Y, (int)enemy.image.Width * enemy.scale, (int)enemy.image.Height * enemy.scale);
                for (int i = 0; i < cannonballs.Count; i++)
                {
                    Rectangle ballHitbox = new Rectangle((int)cannonballs[i].position.X, (int)cannonballs[i].position.Y, (int)cannonballs[i].image.Width * cannonballs[i].scale, (int)cannonballs[i].image.Height * cannonballs[i].scale);
                    
                    if (ballHitbox.Intersects(enemyHitbox))
                    {
                        enemy.position.X = graphics.PreferredBackBufferWidth - 1;
                        enemy.position.Y = (float)MathHelper.Lerp(0, (float)graphics.PreferredBackBufferHeight - 100, (float)r.NextDouble());
                        cannonballs.Remove(cannonballs[i]);
                        i--;
                        score += 10;
                    }
                }
            }
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.DarkBlue);
            spriteBatch.Begin();
            spriteBatch.Draw(cannon.image, cannon.position, null, Color.White, cannon.rotation, cannon.center, 1.0f, SpriteEffects.None, 0);
            foreach (CannonBall ball in cannonballs)
            {
                spriteBatch.Draw(ball.image, ball.position, null, Color.White, ball.rotation, Vector2.Zero, ball.scale, SpriteEffects.None, 1);
            }
            foreach (Enemy enemy in enemies)
            {
                spriteBatch.Draw(enemy.image, enemy.position, null, Color.White, enemy.rotation, Vector2.Zero, enemy.scale, SpriteEffects.None, 0);
            }
            spriteBatch.DrawString(font, "Score: " + score.ToString(), new Vector2(graphics.PreferredBackBufferWidth - 150, 50), new Color(250, 50, 50, 255));
            spriteBatch.End();
            
            base.Draw(gameTime);
        }
    }
}
